package com.uyayo.framework.web.util;

import com.alibaba.fastjson.JSONObject;
import com.uyayo.framework.web.constants.WebConstants;
import com.uyayo.framework.web.model.RequestInfo;
import eu.bitwalker.useragentutils.Browser;
import org.springframework.mobile.device.DeviceType;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import org.springframework.http.HttpHeaders;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;

/**
 * @author hfj
 */
public class WebUtil {
	private final static String REGEX = "[@ `~!#$%^&*()+=|{}':;',//[//]<>/?~！#￥%……&*（）——+|{}【】‘；：”“’。，、？]";

	private final static Pattern STRING_PATTERN = Pattern.compile(REGEX);

	private WebUtil() {
	}

	/**
	 * 得到真实Ip
	 *
	 * @param xForwardedFor
	 * @param proxyClientIP
	 * @param wLProxyClientIP
	 * @param remoteAddr
	 * @return
	 */
	public static String getIpAddr(String xForwardedFor,
								   String proxyClientIP,
								   String wLProxyClientIP,
								   String remoteAddr) {
		String ip = xForwardedFor;
		if (StringUtils.isEmpty(ip)|| WebConstants.UNKNOWN.equalsIgnoreCase(ip)) {
			ip = proxyClientIP;
		} else {
			int index = ip.lastIndexOf(",");
			if (index != -1) {
				ip = ip.substring(index + 1);
			}
		}
		if (StringUtils.isEmpty(ip) || WebConstants.UNKNOWN.equalsIgnoreCase(ip)) {
			ip = wLProxyClientIP;
		}
		if (StringUtils.isEmpty(ip) || WebConstants.UNKNOWN.equalsIgnoreCase(ip)) {
			ip = remoteAddr;
		}
		return ip.trim();
	}

	/**
	 * 获取RequestInfo
	 *
	 * @param request
	 * @return
	 */
	public static RequestInfo getRequestInfo(HttpServletRequest request) {
		RequestInfo requestInfo = new RequestInfo();
		String curIp = WebUtil.getIpAddr(request.getHeader(WebConstants.HEADER_X_FORWARDED_FOR),
				request.getHeader(WebConstants.HEADER_PROXY_CLIENT_IP),
				request.getHeader(WebConstants.HEADER_WL_PROXY_CLIENT_IP),
				request.getRemoteAddr());
		Device device = DeviceUtils.getCurrentDevice(request);
		if (null == device) {
			requestInfo.setDeviceType(WebConstants.UNKNOWN);
		} else if (device.isMobile()) {
			requestInfo.setDeviceType(DeviceType.MOBILE.toString());
		} else if (device.isNormal()) {
			requestInfo.setDeviceType(DeviceType.NORMAL.toString());
		} else if (device.isTablet()) {
			requestInfo.setDeviceType(DeviceType.TABLET.toString());
		} else {
			requestInfo.setDeviceType(WebConstants.UNKNOWN);
		}
		if (!StringUtils.isEmpty(curIp)) {
			requestInfo.setRequestIp(curIp.trim());
		}
		String serverName = request.getServerName();
		String domainName;
		if (serverName.split("\\.").length > 2) {
			domainName = serverName.replaceAll("^.*?\\.", "");
		} else {
			domainName = serverName;
		}
		requestInfo.setDomainName(domainName);
		requestInfo.setWebsite(request.getScheme() + "://" + request.getServerName());
		String userAgent = request.getHeader(HttpHeaders.USER_AGENT);
		if (!StringUtils.isEmpty(userAgent)) {
			UserAgent useragent = UserAgent.parseUserAgentString(userAgent);

			String browser = Optional.ofNullable(useragent.getBrowser()).orElse(Browser.UNKNOWN).getName();
			String operatingSystem = Optional.ofNullable(useragent.getOperatingSystem()).
					orElse(OperatingSystem.UNKNOWN).getName();
			requestInfo.setBrowser(browser);
			requestInfo.setOperatingSystem(operatingSystem);
		}
		return requestInfo;
	}

	/**
	 * servletName是否包含url
	 *
	 * @param servletName 当前域名
	 * @param url         多个已,隔开
	 * @return
	 */
	public static boolean contains(String servletName, String url) {
		return Arrays.stream(url.split(WebConstants.COMMA)).anyMatch(servletName::contains);
	}


	/**
	 * 特殊字符转换为" "后,移除首位空格
	 *
	 * @param str 原字符串
	 * @return To String
	 */
	public static String stringFilter(String str) {
		if (StringUtils.isEmpty(str)) {
			return str;
		}
		return STRING_PATTERN.matcher(str).replaceAll( WebConstants.BLANK).trim();
	}


	/**
	 * 判断ajax请求
	 *
	 * @param request
	 * @return
	 */
	public static boolean isAjaxRequest(HttpServletRequest request) {
		String header = request.getHeader("X-Requested-With");
		if ("XMLHttpRequest".equals(header)) {
			return true;
		} else {
			return false;
		}
	}


	/**
	 * 是否是Ajax请求
	 * @param request
	 * @return
	 */
	public static boolean isAjax(ServletRequest request){
		return "XMLHttpRequest".equalsIgnoreCase(((HttpServletRequest) request).getHeader("X-Requested-With"));
	}

	/**
	 * response 输出JSON
	 * @param response
	 * @param resultMap
	 */
	public static void out(ServletResponse response, Map<String, String> resultMap){

		PrintWriter out = null;
		try {
			response.setCharacterEncoding("UTF-8");
			out = response.getWriter();
			out.println(JSONObject.toJSONString(resultMap));
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(null != out){
				out.flush();
				out.close();
			}
		}
	}
}
